unit ORM.Types.Money;

interface

uses
  ORM.Enumerators;

type
  TMoney = record
  strict private
    FValue : Double;
    FValorReferencia : string;
    function GetValue : Double;
  public
    property Value : Double read GetValue;

    function IsEmpty : Boolean;
    function ToString : string;
    function GetFormatValue : string; overload;
    function GetFormatValue(const pTipoFormatacao : TTipoFormatValor) : string; overload;
    function Equals(const pOther: TMoney): Boolean;
    procedure Clear;

    class operator Implicit(const pValue : Double) : TMoney;
    class operator Implicit(const pValue : TMoney) : Double;

    class operator Add(pLeft, pRigth : TMoney) : TMoney;
    class operator Subtract(pLeft, pRigth : TMoney) : TMoney;
    class operator Multiply(pLeft, pRigth : TMoney) : TMoney;
    class operator Divide(pLeft, pRigth : TMoney) : TMoney;

    class operator Equal(pLeft, pRigth: TMoney) : Boolean;
    class operator GreaterThan(pLeft , pRigth : TMoney) : Boolean;
    class operator GreaterThanOrEqual(pLeft , pRigth : TMoney) : Boolean;
    class operator LessThan(pLeft , pRigth : TMoney) : Boolean;
    class operator LessThanOrEqual(pLeft , pRigth : TMoney) : Boolean;
    class operator NotEqual(pLeft , pRigth : TMoney) : Boolean;

    constructor Create( const pValue : Double);
  end;

implementation

uses
  SysUtils, ORM.Types.Base, System.Generics.Defaults;

{ TMoney }


class operator TMoney.Add(pLeft, pRigth: TMoney): TMoney;
begin
  Result := pLeft.Value + pRigth.Value;
end;

procedure TMoney.Clear;
begin
  FValue := 0;
  FValorReferencia := EmptyStr;
end;

constructor TMoney.Create(const pValue : Double);
begin
  FValue := pValue;
  FValorReferencia := CValorReferencia;
end;

class operator TMoney.Divide(pLeft, pRigth: TMoney): TMoney;
begin
  Result := pLeft.Value / pRigth.Value;
end;

class operator TMoney.Equal(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Equals(pRigth);
end;

function TMoney.Equals(const pOther: TMoney): Boolean;
begin
  if not IsEmpty and not pOther.IsEmpty then
    Result := TEqualityComparer<TMoney>.Default.Equals(Value, pOther.Value)
  else
    Result := IsEmpty = pOther.IsEmpty;
end;

class operator TMoney.Implicit(const pValue: TMoney): Double;
begin
  Result := pValue.Value;
end;

function TMoney.GetFormatValue(const pTipoFormatacao: TTipoFormatValor): string;
begin
  case pTipoFormatacao of
    tpDuas: Result := FormatFloat(',0.00', FValue);
    tpQuatro: Result := FormatFloat(',0.0000', FValue);
  end;
end;

function TMoney.GetFormatValue: string;
begin
  Result := FormatFloat(',0.00', FValue);
end;

function TMoney.GetValue: Double;
begin
  Result := FValue;
end;

class operator TMoney.GreaterThan(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Value > pRigth.Value;
end;

class operator TMoney.GreaterThanOrEqual(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Value >= pRigth.Value;
end;

class operator TMoney.Implicit(const pValue: Double): TMoney;
begin
  Result := TMoney.Create(pValue);
end;

function TMoney.IsEmpty: Boolean;
begin
  Result := Length(FValorReferencia) = 0;
end;

class operator TMoney.LessThan(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Value < pRigth.Value;
end;

class operator TMoney.LessThanOrEqual(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Value <= pRigth.Value;
end;

class operator TMoney.Multiply(pLeft, pRigth: TMoney): TMoney;
begin
  Result := pLeft.Value * pRigth.Value;
end;

class operator TMoney.NotEqual(pLeft, pRigth: TMoney): Boolean;
begin
  Result := pLeft.Value <> pRigth.Value;
end;

class operator TMoney.Subtract(pLeft, pRigth: TMoney): TMoney;
begin
  Result := pLeft.Value - pRigth.Value;
end;

function TMoney.ToString: string;
begin
  Result := FloatToStr(FValue);
end;

end.
